package com.danci.service.impl;

import cn.hutool.core.io.resource.InputStreamResource;
import cn.hutool.core.util.IdUtil;
import cn.hutool.crypto.digest.MD5;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.danci.common.Result;
import com.danci.dto.MyDataDto;
import com.danci.dto.UserDto;
import com.danci.dto.UserLoginDto;
import com.danci.dto.UserRequest;
import com.danci.entity.Userinfo;
import com.danci.mapper.UserinfoMapper;
import com.danci.service.IUserinfoService;
import lombok.AllArgsConstructor;
import org.springframework.data.redis.connection.BitFieldSubCommands;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author xxx
 * @since 2024-05-13
 */
@Service
@AllArgsConstructor
public class UserinfoServiceImpl extends ServiceImpl<UserinfoMapper, Userinfo> implements IUserinfoService {

    private final UserinfoMapper userinfoMapper;

    private static final String SIGN_KEY_PREFIX = "user:sign:";
    private final StringRedisTemplate redisTemplate;
    @Override
    public Result login(UserLoginDto userLoginDto) {
        if (!StringUtils.hasText(userLoginDto.getUsername()) || !StringUtils.hasText(userLoginDto.getPassword())){
            return Result.fail("用户名或密码不能为空");
        }
        QueryWrapper<Userinfo> wrapper = new QueryWrapper<>();
        wrapper.eq("username",userLoginDto.getUsername());
        Userinfo userinfo = userinfoMapper.selectOne(wrapper);
        if (ObjectUtils.isEmpty(userinfo)) {
            return Result.fail("账号未注册");
        }else {
            if (userinfo.getPassword().equals(MD5.create().digestHex16(userLoginDto.getPassword()))){
                return Result.success(userinfo.getId());
            }else {
                return Result.fail("密码错误");
            }
        }
    }

    @Override
    public Result register(UserLoginDto userLoginDto) {
        if (!StringUtils.hasText(userLoginDto.getUsername()) || !StringUtils.hasText(userLoginDto.getPassword())){
            return Result.fail("用户名或密码不能为空");
        }
        if (userinfoMapper.selectOne(new QueryWrapper<Userinfo>().eq("username",userLoginDto.getUsername())) != null){
            return Result.fail("用户名已存在");
        }
        Userinfo userinfo = new Userinfo();
        userinfo.setId(IdUtil.fastSimpleUUID());
        userinfo.setPassword(MD5.create().digestHex16(userLoginDto.getPassword()));
        userinfo.setUsername(userLoginDto.getUsername());
        userinfo.setPhone("");
        userinfo.setNickname("爱吃瓜的猹");
        userinfo.setSchool("");
        userinfo.setAvatar("");
        userinfo.setSign("");
        userinfo.setLid("");
        userinfo.setPlanDay(20);
        userinfo.setAddress("");
        int insert = userinfoMapper.insert(userinfo);
        if (insert > 0){
            return Result.success(userinfo.getId());
        }else {
            return Result.fail("注册失败");
        }
    }

    @Override
    public Result updatePlanDay(UserRequest userRequest) {
        if (userRequest.getPlanDay() == null) {
            return Result.fail("计划天数参数错误");
        }
        try {
            userinfoMapper.updatePlanDay(userRequest.getPlanDay(),userRequest.getUserId());
            return Result.success(null);
        }catch (Exception e) {
            return Result.fail("更新失败："+e.getMessage());
        }
    }

    @Override
    public Result updateLid(UserRequest userRequest) {
        if (userRequest.getLid() == null) {
            return Result.fail("词汇参数错误");
        }
        try {
            userinfoMapper.updateLid(userRequest.getLid(),userRequest.getUserId());
            return Result.success(null);
        }catch (Exception e) {
            return Result.fail("更新失败："+e.getMessage());
        }
    }

    @Override
    public Result getMyData(UserRequest userRequest) {
        // 获取用户信息
        MyDataDto myData = userinfoMapper.getMyData(userRequest.getUserId());
        // 处理连续签到的天数
        //2. 获取日期
        LocalDateTime now = LocalDateTime.now();
        //3. 拼接key
        String keySuffix = now.format(DateTimeFormatter.ofPattern(":yyyyMM"));
        String key = SIGN_KEY_PREFIX + userRequest.getUserId() + keySuffix;
        //4. 获取今天是本月的第几天
        int dayOfMonth = now.getDayOfMonth();
        //5. 获取本月截至今天为止的所有的签到记录，返回的是一个十进制的数字 BITFIELD sign:5:202301 GET u3 0
        List<Long> result = redisTemplate.opsForValue().bitField(
                key,
                BitFieldSubCommands.create()
                        .get(BitFieldSubCommands.BitFieldType.unsigned(dayOfMonth)).valueAt(0));
        //没有任务签到结果
        if (result == null || result.isEmpty()) {
            myData.setSignDay(0);
            return Result.success(myData);
        }
        Long num = result.get(0);
        if (num == null || num == 0) {
            myData.setSignDay(0);
            return Result.success(myData);
        }
        //6. 循环遍历
        int count = 0;
        //如果为0，签到结束
        while ((num & 1) != 0) {
            //6.1 让这个数字与1 做与运算，得到数字的最后一个bit位 判断这个数字是否为0
            count++;
            num >>>= 1;
        }
        myData.setSignDay(count);

        return Result.success(myData);
    }

    @Override
    public Result updateUserInfo(UserDto userDto) {
        // 修改昵称、签名、学校、地址
        userinfoMapper.updateUserInfo(userDto);
        return Result.success("更新成功");
    }

    @Override
    public Result updateAvatar(MultipartFile file, String userId) {
        String FILE_UPLOADER_HOST = "http://119.3.239.84:8080";
        Map<String, Object> parametersFromClient = new HashMap<>();
        try {
            InputStreamResource isr = new InputStreamResource(file.getInputStream(),
                    file.getOriginalFilename());

            Map<String, Object> params = new HashMap<>();
            params.put("file", isr);
            params.put("path", "jianshen");
            params.put("output", "json");
            String resp = HttpUtil.post(FILE_UPLOADER_HOST + "/upload", params);
            JSONObject json = JSONUtil.parseObj(resp);
            String path =  FILE_UPLOADER_HOST + json.get("src")+"?download=0";
            parametersFromClient.put("file_path", path);
            parametersFromClient.put("file_name", json.get("src"));
            Userinfo userinfo = new Userinfo();
            userinfo.setAvatar(path);
            userinfo.setId(userId);
            userinfoMapper.updateById(userinfo);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return Result.success(parametersFromClient);
    }
}
